package com.example.peanutsubway.web;


import com.example.peanutsubway.annotation.ResponseTypeAnnotation;
import com.example.peanutsubway.myEnum.ResponseEnum;
import com.example.peanutsubway.util.ConvertEntity;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Map;


public class BaseServlet<T> extends HttpServlet {

    private final Class<T> entityClass;// 获取子类中需要反射的实体类的类型
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected HttpSession session;
    protected ServletContext application;


    public BaseServlet() {
        // 获取子类中 extends BaseServlet<类> 泛型类型
        entityClass = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.request = request;
        this.response = response;
        this.session = request.getSession();
        this.application = getServletContext();
        request.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        // 1.调用子类（UserinfoServlet）中方法
        // 1.1 获取method请求参数
        String methodStr = request.getParameter("method");// 子类中方法的方法名
        try {
            // 1.2 通过method获取子类中的Method
            Method[] declaredMethods = this.getClass().getDeclaredMethods();// 获取子类中定义的方法（共有、私有的、受保护的、默认的）
            Method method = null;
            for (Method declaredMethod : declaredMethods) {
                if (declaredMethod.getName().equals(methodStr)) {
                    method = declaredMethod;
                    break;
                }
            }

            if (method != null) {
                Object[] objects = new Object[method.getParameterCount()];
                // 1.3 获取传递子类方法中的参数值
                if (method.getParameterCount() > 0) {
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    for (int i = 0; i < parameterTypes.length; i++) {
                        Class<?> parameterType = parameterTypes[i];
                        if (parameterType == HttpServletRequest.class) {
                            objects[i] = request;
                        } else if (parameterType == HttpServletResponse.class) {
                            objects[i] = response;
                        } else if (parameterType == entityClass) {// 实体类
                            Map<String, String[]> parameterMap = request.getParameterMap();
                            T entity = ConvertEntity.convertEntityByData(parameterMap, entityClass);
                            objects[i] = entity;
                        } else if (parameterType.getSuperclass() == entityClass) {
                            Map<String, String[]> parameterMap = request.getParameterMap();
                            Object entity = ConvertEntity.convertEntityByData(parameterMap, parameterType);
                            objects[i] = entity;
                        }
                    }
                }

                // 1.4通过method对象调用当前要执行的方法
                Object result = method.invoke(this, objects);
                // 2.处理响应的数据
                if (result != null) {
                    // 方法上的ResponseTypeAnnotation注解
                    ResponseTypeAnnotation responseTypeAnnotation = null;
                    // 获取方法上的所有的注解
                    Annotation[] annotations = method.getAnnotations();
                    // 遍历annotations
                    for (Annotation annotation : annotations) {
                        // annotation.annotationType():获取注解类的类型-->Class
                        // ResponseTypeAnnotation.class:ResponseTypeAnnotation的类型
                        if (annotation.annotationType() == ResponseTypeAnnotation.class) {
                            responseTypeAnnotation = (ResponseTypeAnnotation) annotation;
                            break;
                        }
                    }

                    String content = result.toString();
                    if (responseTypeAnnotation != null) {
                        ResponseEnum type = responseTypeAnnotation.type();
                        if (type.equals(ResponseEnum.AJAX)) {
                            PrintWriter writer = response.getWriter();
                            writer.write(content);
                            writer.flush();
                            writer.close();
                        } else if (type.equals(ResponseEnum.FORWARD)) {
                            request.getRequestDispatcher(content).forward(request, response);
                        } else if (type.equals(ResponseEnum.REDIRECT)) {
                            response.sendRedirect(content);
                        }
                    } else {
                        PrintWriter writer = response.getWriter();
                        writer.write(content);
                        writer.flush();
                        writer.close();
                    }
                }
            }
        } catch (IllegalAccessException | InvocationTargetException | NoSuchFieldException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}
